<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DB;
use App\Support\MemcacheSASL;
use Validator;

class BaseModel extends Model
{
    protected $rules = [];

    protected $message = [];

    public $error;

    public function __construct()
    {
//        $this->memcache = new MemcacheSASL;
//        $this->memcache->addServer(env('MEMCACHE_HOST', '127.0.0.1'), env('MEMCACHE_PORT', '11211'));
    }

    public function getError()
    {
        return $this->error;
    }

    /**
     * 删除指定MC
     */
//    public function delMc($key)
//    {
//        if (is_array($key)) {
//            foreach ($key as $v) {
//                $this->memcache->delete($v);
//            }
//        } else {
//            $this->memcache->delete($key);
//        }
//    }

    public function scopeMultiWhere($query, $arr = '')
    {
        if (!is_array($arr)) {
            return $query;
        }
        if (empty($arr)) {
            return $query;
        }
        foreach ($arr as $key => $value) {
            //判断$arr
            if (is_array($value)) {
                $value[0] = strtolower($value[0]);
                switch ($value[0]) {
                    case 'like';
                        $query = $query->where($key, $value[0], $value[1]);
                        break;
                    case 'in':
                        $query = $query->whereIn($key, $value[1]);
                        break;
                    case 'between':
                        $query = $query->whereBetween($key, [$value[1][0], $value[1][1]]);
                        break;
                    case 'glt'://大于小于等于比较查询   $where['money'] = ['glt',[['>',1],['<=',2]]];
                        $query = $query->where($key, $value[1][0][0], $value[1][0][1])->where($key, $value[1][1][0], $value[1][1][1]);
                        break;
                    default:
                        $query = $query->where($key, $value[0], $value[1]);
                        break;
                }
            } else {
                $query = $query->where($key, $value);
            }
        }
        return $query;
    }


    public function scopeMultiJoin($query, $arr = '')
    {
        if (!is_array($arr)) {
            return $query;
        }
        if (empty($arr)) {
            return $query;
        }
        foreach ($arr as $key => $value) {
            //判断$arr
            if (is_array($value)) {
                $value[0] = strtolower($value[0]);
                $query = $query->join($key, $value[0], '=', $value[1]);
                if ($value[0] == 'left') {
                    $query = $query->leftJoin($key, $value[0], '=', $value[1]);
                }
            }
        }
        return $query;
    }


    public function scopeMultiHaving($query, $arr = '')
    {
        if (!is_array($arr)) {
            return $query;
        }
        if (empty($arr)) {
            return $query;
        }
        foreach ($arr as $key => $value) {
            //判断$arr
            if (is_array($value)) {
                $value[0] = strtolower($value[0]);
                if ($value[0]) {
                    $query = $query->having($key, $value[0], $value[1]);
                }
            } else {
                $query = $query->having($key, '=', $value);
            }
        }
        return $query;
    }

    public function scopeMultiOrder($query, $arr = '')
    {
        if (!is_array($arr)) {
            return $query;
        }
        if (empty($arr)) {
            return $query;
        }
        foreach ($arr as $key => $value) {
            $query = $query->orderBy($key, $value);
        }
        return $query;
    }

    public function scopeWithCertain($query, $relation, $columns, array $where = [], array $order = [])
    {
        return $query->with([$relation => function ($query) use ($columns, $where, $order) {
            $query->multiSelect($columns)->multiWhere($where)->multiOrder($order);
        }]);
    }

    public function scopeMultiSelect($query, $fileds = '')
    {
        if (!$fileds) {
            $fileds = '*';
        }
        if (is_array($fileds)) {
            $fileds = implode(',', $fileds);
        }
        return $query->select(DB::raw((string)$fileds));
    }

    public function _getOneById($id, $idField = 'id', $fields = "*")
    {
        return $this->multiSelect($fields)->multiWhere([$idField => $id])->first();
    }


    public function _getOne(array $where, $fields = "*")
    {
        return $this->multiSelect($fields)->multiWhere($where)->first();
    }

    /**
     * 按条件查询全部数据,根据配置显示条数显示
     */
    public function _getList(array $where = [], $fields = '*', array $order = [], $pageSize = 0)
    {
        if ($pageSize) {
            return $this->multiSelect($fields)->multiWhere($where)->multiOrder($order)->paginate($pageSize);
        } else {
            return $this->multiSelect($fields)->multiWhere($where)->multiOrder($order)->get();
        }
    }

    /**
     * 添加数据
     * @param $data
     */
    public function _add(array $data)
    {
        return $this->insert($data);
    }

    /**
     * 添加和更新数据（默认执行添加操作，当data中有id存在的时候执行更新）
     * @param $data
     */
    public function _save(array $data)
    {
        if (is_array($data) && count($data)) {
            foreach ($data as $key => $value) {
                $this->$key = $value;
            }
        }
        if ($this->id) {
            unset($data['id']);
            return $this->_update(['id' => $this->id], $data);
        }
        return $this->save();
    }

    /**
     * 修改数据
     */
    public function _update(array $where = [], array $data)
    {
        return $this->multiWhere($where)->update($data);
    }

    //批量更新
    public function _updateBatch($multipleData = [])
    {
        try {
            if (empty($multipleData)) {
                $this->error = "数据不能为空";
                return false;
            }
            $tableName = DB::getTablePrefix() . $this->getTable(); // 表名
            $firstRow  = current($multipleData);

            $updateColumn = array_keys($firstRow);
            // 默认以id为条件更新，如果没有ID则以第一个字段为条件
            $referenceColumn = isset($firstRow['id']) ? 'id' : current($updateColumn);
            unset($updateColumn[0]);
            // 拼接sql语句
            $updateSql = "UPDATE " . $tableName . " SET ";
            $sets      = [];
            $bindings  = [];
            foreach ($updateColumn as $uColumn) {
                $setSql = "`" . $uColumn . "` = CASE ";
                foreach ($multipleData as $data) {
                    $setSql .= "WHEN `" . $referenceColumn . "` = ? THEN ? ";
                    $bindings[] = $data[$referenceColumn];
                    $bindings[] = $data[$uColumn];
                }
                $setSql .= "ELSE `" . $uColumn . "` END ";
                $sets[] = $setSql;
            }
            $updateSql .= implode(', ', $sets);
            $whereIn   = collect($multipleData)->pluck($referenceColumn)->values()->all();
            $bindings  = array_merge($bindings, $whereIn);
            $whereIn   = rtrim(str_repeat('?,', count($whereIn)), ',');
            $updateSql = rtrim($updateSql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")";
            // 传入预处理sql语句和对应绑定数据
            $res = DB::update($updateSql, $bindings);
            if(!$res) {
                $this->error = "更新失败！";
                return false;
            }
            return '更新成功！';
        } catch (\Exception $e) {
            $this->error = "数据结构错误！";
            return false;
        }
    }

    /**
     * 删除数据
     */
    public function _del(array $where = [])
    {
        return $this->multiWhere($where)->delete();
    }

    public function _count(array $where = [], $field = '*')
    {
        return $this->multiWhere($where)->count($field);
    }

    public function _sum(array $where = [], $field)
    {
        return $this->multiWhere($where)->sum($field);
    }

    public function _max(array $where = [], $field)
    {
        return $this->multiWhere($where)->max($field);
    }

    public function _min(array $where = [], $field)
    {
        return $this->multiWhere($where)->min($field);
    }

    public function _inc(array $where = [], $field, $num, array $data = [])
    {
        return $this->multiWhere($where)->increment($field, $num, $data);
    }

    public function _dec(array $where = [], $field, $num, array $data = [])
    {
        return $this->multiWhere($where)->decrement($field, $num, $data);
    }

    public function _start()
    {
        DB::beginTransaction();
    }

    public function _commit()
    {
        DB::commit();
    }

    public function _rollBack()
    {
        DB::rollBack();
    }

    public function _getPageList(array $where = [], $fields = '*', array $order = [], $pageSize = 10, $pageLength = 5)
    {
        $rows = $this->_getList($where, $fields, $order, $pageSize);
        if ($rows) {
            $rows = $rows->toArray();
            $rows['pageNoList'] = $this->getPageNoList($rows['last_page'], request('page', 1), $pageLength);
        }
        return $rows;
    }


    public function getPageNoList($totalPage, $pageNo, $pageSize)
    {
        $disPageList = $pageNo + $pageSize - 1;//最大链接显示数额赋值，公式为"当前页数 + 最大链接显示数额 -1"
        //前页面导航页数
        $pageNoList = [];
        //循环显示出当前页面导航页数
        if ($disPageList <= $totalPage) {
            for ($i = $pageNo; $i <= $disPageList; $i++) {
                $pageNoList[] = $i;
            }
            return $pageNoList;
        }
        if ($totalPage < $pageSize) {
            for ($i = 1; $i <= $totalPage; $i++) {
                $pageNoList[] = $i;
            }
            return $pageNoList;
        }
        $start = $totalPage - $pageSize + 1;
        for ($i = $start; $i <= $totalPage; $i++) {
            $pageNoList[] = $i;
        }
        return $pageNoList;
    }

    /*
     * 打印sql
     */
    public function _openQueryLog()
    {
        DB::connection()->enableQueryLog();
    }

    public function _getQueryLog()
    {
        return DB::getQueryLog();
    }

    public function _validate($data, $rules = 'rules', $message = 'message')
    {
        $validation = Validator::make($data, $this->$rules, $this->$message);
        if ($validation->passes()) {
            return true;
        }
        $this->error = $validation->messages()->first();
        return false;
    }

}